package controllers

import (
	"encoding/json"
	"fmt"
	"net/url"
	"os"
	"os/exec"
	"strconv"
	"time"

	"github.com/neo4j/neo4j-go-driver/v4/neo4j"
)

func (c *TaskController) Post() { //创建任务
	username := c.GetString("username")
	name := c.GetString("name")
	t := c.GetString("type")
	create_time := time.Unix(time.Now().Unix(), 0).Format("2006-01-02 15:04:05")
	driver, session := GetNeo4jConn()
	defer driver.Close()
	defer session.Close()
	r, _ := session.ReadTransaction(func(tx neo4j.Transaction) (interface{}, error) {
		r, err := tx.Run("match (n:User{username:$username})-[r:Control{permission:'own'}]->(t:Task{name:$name}) return t.name as name",
			map[string]interface{}{"username": username, "name": name})
		if err != nil {
			panic(err)
		}
		if r.Next() {
			return 0, err //有同名的
		} else {
			return 1, err
		}
	})

	flag, _ := r.(int)
	if flag == 0 {
		c.Ctx.WriteString("0")
		return
	}

	_, _ = session.WriteTransaction(func(tx neo4j.Transaction) (interface{}, error) {
		result, err := tx.Run(`match (n:User{username:$username}) 
		create (n)-[r:Control{permission:'own'}]->(t:Task{name:$name,t:$t,created:$c,modified:$c,owner:$o,last:1,totalnum:1})`,
			map[string]interface{}{"username": username, "name": name, "t": t, "c": create_time, "o": username})
		if err != nil {
			panic(err)
		}
		if t == "1" {
			_, err = tx.Run(`match (n:User{username:$username})-[r:Control{permission:'own'}]->(t:Task{name:$name}) 
			create (p:Page{order:1,title:'',targetid:'',problem:'',advice:'',pic:''})<-[i:Include]-(t)`,
				map[string]interface{}{"username": username, "name": name})
		} else if t == "2" {
			t := time.Now()
			s := t.Format("2006-01-02")
			_, err = tx.Run(`match (n:User{username:$username})-[r:Control{permission:'own'}]->(t:Task{name:$name}) 
			create (t)-[i:Include]->(p:Page{order:1,title:'',case_num:'',product_class:'',name:'',version:'',app_class:'', 
			date:$d, feature:'', abstract:'', page_num:'', detail:'', idea:'', username:$username})`,
				map[string]interface{}{"username": username, "name": name, "d": s})
		} else if t == "3" {
			_, err = tx.Run(`match (n:User{username:$username})-[r:Control{permission:'own'}]->(t:Task{name:$name}) 
			create (t)-[i:Include]->(p:Page{order:1,title:''}),(p)-[k:Inc]->(col:Col{title:'',col:0})`, map[string]interface{}{"username": username, "name": name})
		}
		if err != nil {
			panic(err)
		}
		return result, err
	})
	c.Ctx.WriteString("1")
}

func (c *TaskController) Get() { //获取任务列表
	page := c.GetString("page")
	sort := c.GetString("sort")   //排序依据 created or modified
	order := c.GetString("order") //升序 asc 降序 desc
	owner := c.GetString("owner")
	driver, session := GetNeo4jConn()
	defer driver.Close()
	defer session.Close()
	results, _ := session.ReadTransaction(func(tx neo4j.Transaction) (interface{}, error) {
		pagenum, _ := strconv.Atoi(page)
		var r neo4j.Result
		var err error
		if owner == "全部" {
			r, err = tx.Run(`match (t:Task) return t.name as name, 
			t.t as ty, t.created as c, 
			t.modified as m, 
			t.owner as owner order by t.`+sort+" "+order+` skip ($page-1)*10 limit 10`,
				map[string]interface{}{"page": pagenum})
		} else {
			r, err = tx.Run(`match (t:Task)<-[:Control]-(u:User{username:$owner}) return t.name as name, 
			t.t as ty, t.created as c, 
			t.modified as m, 
			t.owner as owner order by t.`+sort+" "+order+` skip ($page-1)*10 limit 10`, map[string]interface{}{"owner": owner, "page": pagenum})
		}
		if err != nil {
			panic(err)
		}
		var objs []Taskitem
		for r.Next() {
			result := r.Record()
			name, _ := result.Get("name")
			ty, _ := result.Get("ty")
			created, _ := result.Get("c")
			modified, _ := result.Get("m")
			owner, _ := result.Get("owner")
			objs = append(objs, Taskitem{name.(string), created.(string), modified.(string), owner.(string), ty.(string)})
		}
		return objs, nil
	})
	c.Data["json"] = results
	c.ServeJSON()
}

func (c *TaskController) Total() {
	owner := c.GetString("owner")
	driver, session := GetNeo4jConn()
	defer driver.Close()
	defer session.Close()
	results, _ := session.ReadTransaction(func(tx neo4j.Transaction) (interface{}, error) {
		var r neo4j.Result
		var err error
		if owner == "全部" {
			r, err = tx.Run("match (t:Task) return count(t) as count", map[string]interface{}{})

		} else {
			r, err = tx.Run("match (t:Task)<-[:Control]-(u:User{username:$owner}) return count(t) as count", map[string]interface{}{"owner": owner})
		}
		if err != nil {
			panic(err)
		}

		if r.Next() {
			record := r.Record()
			r, _ := record.Get("count")
			return r, err
		} else {
			return 0, err
		}
	})
	rstr := strconv.Itoa(int(results.(int64)))
	c.Ctx.WriteString(rstr)
}

func (c *TaskController) Exportpptx() { //导出ppt
	encode_user := c.Ctx.Input.Param(":user")
	encode_name := c.Ctx.Input.Param(":name")
	user, _ := url.QueryUnescape(encode_user)
	task_name, _ := url.QueryUnescape(encode_name)
	task_type := c.GetString("type")
	driver, session := GetNeo4jConn()
	defer driver.Close()
	defer session.Close()

	var f *os.File

	folder := "user/" + user
	_, e := os.Stat(folder)

	if os.IsNotExist(e) {
		os.MkdirAll(folder, 0666)
	}
	filename := folder + "/" + task_name + ".json"
	f, err := os.OpenFile(filename, os.O_CREATE|os.O_RDWR, 0777)

	if err != nil {
		panic(err)
	}

	var results interface{}
	if task_type == "2" { //特色化案例库
		results, _ = session.ReadTransaction(func(tx neo4j.Transaction) (interface{}, error) {
			results, err := tx.Run(`match (t:Task{name:$name})<-[r:Control]-(u:User{username:$username}), 
			(t)-[i:Include]->(p:Page) 
			return p.abstract as abstract, p.case_num as case_num,
			p.app_class as app_class, p.date as mdate,
			p.detail as detail, p.feature as feature, p.idea as idea,
			p.name as name, p.page_num as page_num, p.product_class as product_class,
			p.title as title,p.recorder as recorder, p.version as version,p.order as order order by p.order`,
				map[string]interface{}{"name": task_name, "username": user})
			if err != nil {
				panic(err)
			}
			var pages []PageCase
			for results.Next() {
				var page PageCase
				record := results.Record()
				case_num, _ := record.Get("case_num")
				product_class, _ := record.Get("product_class")
				feature, _ := record.Get("feature")
				page_num, _ := record.Get("page_num")
				name, _ := record.Get("name")
				abstract, _ := record.Get("abstract")
				detail, _ := record.Get("detail")
				version, _ := record.Get("version")
				app_class, _ := record.Get("app_class")
				mdate, _ := record.Get("mdate")
				recorder, _ := record.Get("recorder")
				idea, _ := record.Get("idea")
				order, _ := record.Get("order")
				page.Case_num, _ = case_num.(string)
				page.Product_class, _ = product_class.(string)
				page.Feature, _ = feature.(string)
				page.Page_num, _ = page_num.(string)
				page.Name, _ = name.(string)
				page.Abstract, _ = abstract.(string)
				page.Detail, _ = detail.(string)
				page.Version, _ = version.(string)
				page.App_class, _ = app_class.(string)
				page.Date, _ = mdate.(string)
				page.Username, _ = recorder.(string)
				page.Idea, _ = idea.(string)
				page.Order, _ = order.(int64) //
				r, e := tx.Run(`match (u:User{username:$user})-[r:Control]->(t:Task{name:$name}),
				(t)-[i:Include]->(p:Page{order:$order}), (p)-[c:Contains]->(pic:Pic) return c.title as title, pic.path as path, c.order as order order by c.order`,
					map[string]interface{}{"user": user, "name": task_name, "order": page.Order})
				if e != nil {
					panic(e)
				}

				for r.Next() {
					item := r.Record()
					var pic Pic
					title, _ := item.Get("title")
					path, _ := item.Get("path")
					order, _ := item.Get("order")
					pic.Title, _ = title.(string)
					pic.Path, _ = path.(string)
					pic.Order, _ = order.(int64)
					page.Pics = append(page.Pics, pic)
				}
				pages = append(pages, page)
			}

			return pages, err
		})
	} else { //竞品分析
		results, _ = session.ReadTransaction(func(tx neo4j.Transaction) (interface{}, error) {
			result, _ := tx.Run(`match (t:Task{name:$name})<-[c:Control]-(u:User{username:$user}),(t)-[i:Include]->(p:Page) 
			return p.advice as advice, p.problem as problem, p.targetid as targetid,
			p.title as title, p.order as order order by order`, map[string]interface{}{"user": user, "name": task_name})
			if err != nil {
				panic(err)
			}
			var pages []Page
			for result.Next() {
				var page Page
				record := result.Record()
				advice, _ := record.Get("advice")
				problem, _ := record.Get("problem")
				targetid, _ := record.Get("targetid")
				title, _ := record.Get("title")
				order, _ := record.Get("order")
				page.Advice, _ = advice.(string)
				page.Problem, _ = problem.(string)
				page.Target, _ = targetid.(string)
				page.Title, _ = title.(string)
				orderint, _ := order.(int64)
				r, err := tx.Run(`match (a:Assess{id:$id}) return a.item as item, a.priority as priority, 
				a.target as target_content, a.type as type`, map[string]interface{}{"id": page.Target})
				if err != nil {
					panic(err)
				}
				if r.Next() {
					rec := r.Record()
					item, _ := rec.Get("item")
					priority, _ := rec.Get("priority")
					target_content, _ := rec.Get("target_content")
					t, _ := rec.Get("type")
					page.Item, _ = item.(string)
					page.Priority, _ = priority.(string)
					page.Target_content, _ = target_content.(string)
					page.Type, _ = t.(string)
				}

				r, e := tx.Run(`match (u:User{username:$user})-[r:Control]->(t:Task{name:$name}),
				(t)-[i:Include]->(p:Page{order:$order}), (p)-[c:Contains]->(pic:Pic) return c.title as title, pic.path as path, c.order as order order by c.order`,
					map[string]interface{}{"user": user, "name": task_name, "order": orderint})
				if e != nil {
					panic(e)
				}

				var pics []Pic
				for r.Next() {
					rec := r.Record()
					var pic Pic
					title, _ := rec.Get("title")
					path, _ := rec.Get("path")
					order, _ := rec.Get("order")
					pic.Title, _ = title.(string)
					pic.Path, _ = path.(string)
					pic.Order, _ = order.(int64)
					pics = append(pics, pic)
				}
				page.Pics = pics
				pages = append(pages, page)
			}
			return pages, nil
		})
	}
	j, _ := json.Marshal(results)
	_, err = f.WriteString(string(j))
	if err != nil {
		panic(err)
	}
	f.Close()
	_, file_err := os.Stat("user/" + user + "/" + task_name + ".pptx")
	if os.IsExist(file_err) { //如果存在 删除
		e := os.Remove("user/" + user + "/" + task_name + ".pptx")
		if e != nil {
			panic(e)
		}
	}
	_, file_err = os.Stat("user/" + user + "/" + task_name + ".xls")
	if os.IsExist(file_err) { //如果存在 删除
		e := os.Remove("user/" + user + "/" + task_name + ".xls")
		if e != nil {
			panic(e)
		}
	}
	cmd := exec.Command("python3", "myppt.py", user, task_name, task_type)
	e = cmd.Run()
	if e != nil {
		fmt.Print(e)
	}
	c.Ctx.WriteString("1")

}

func (c *TaskController) Delete() {
	username, _ := url.QueryUnescape(c.Ctx.GetCookie("username"))
	task_name := c.GetString("name")

	driver, session := GetNeo4jConn()
	defer driver.Close()
	defer session.Close()

	_, _ = session.WriteTransaction(func(tx neo4j.Transaction) (interface{}, error) {
		_, err := tx.Run(`match (t:Task{name:$name})<-[r:Control]-(u:User{username:$username}), 
		(t)-[i:Include]->(p:Page), (p)-[c:Contains]->(pic:Pic)  
		delete c`,
			map[string]interface{}{"name": task_name, "username": username})
		if err != nil {
			panic(err)
		}
		_, err = tx.Run(`match (t:Task{name:$name})<-[r:Control]-(u:User{username:$username}), 
		(t)-[i:Include]->(p:Page) 
		delete r,i,t,p`,
			map[string]interface{}{"name": task_name, "username": username})
		return nil, err
	})
	c.Ctx.WriteString("1")
}
